package com.self.structure;


import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

public class MapMain {

    private static ConcurrentHashMap<String, Future<Object>> map = new ConcurrentHashMap<>(1);

    public static void main(String[] args) {

        ExecutorService executorService = Executors.newFixedThreadPool(10);
        Map<String,Object> map = new HashMap<>();
        for (int i= 0; i < 100000; i++) {
            final String key = "test-"+i;
            final int val = i;
            executorService.execute(() -> map.put(key,val));
        }

        try {
            executorService.shutdown();
            executorService.awaitTermination(1000,TimeUnit.SECONDS);

            System.out.println(map.size());

            int count = 0;
            for (Map.Entry<String,Object> entry : map.entrySet()) {
                count = count + (entry == null ? 0: 1);
            }
            System.out.println(count);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void testFuture() {

        String key = "test-future";

        for (int i=0;i<20;i++) {

            new Thread(() -> {

                try {

                    Object val = getValueFromCache(key, TimeUnit.MILLISECONDS.toNanos(1));

                    System.out.println(Thread.currentThread().getName()+"-getValue = "+val);

                } catch (Exception e) {
                    e.printStackTrace();
                }

            },"thread-"+i).start();
        }
    }

    private static Object getValueFromCache(String cacheKey,long timeout) {

        try {

            Future<Object> futureTask;

            if((futureTask = map.get(cacheKey)) == null) {
                futureTask = new FutureTask<>(() -> {
                    LockSupport.parkNanos(timeout);
                    return "future-finish";
                });

                if(map.putIfAbsent(cacheKey,futureTask) != null) {
                    futureTask = map.get(cacheKey);
                } else {
                    ((FutureTask<Object>) futureTask).run();
                }
            }

            return futureTask.get();

        } catch (Exception e) {
            e.printStackTrace();
        }

        return "nil";
    }
}
